﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using TomanuExtensions;
using System.Diagnostics;

namespace RaytracerLib.MathLib
{
    public static class LowDiscrepancyMath
    {
        public static double RadicalInverse(int a_n, int a_base)
        {
            double y = 0;
            double b = a_base;
            while (a_n > 0)
            {
                int d_i = a_n % a_base;
                y += d_i / b;
                a_n /= a_base;
                b *= a_base;
            }
            return y;
        }

        public static double FoldedRadicalInverse(int a_n, int a_base)
        {
            double y = 0;
            double b = a_base;
            int fi = 0;
            while (a_n > 0)
            {
                int d_i = (a_n + fi) % a_base;
                y += d_i / b;
                a_n /= a_base;
                b *= a_base;
                fi++;
            }
            return y;
        }

        public static double StarDiscrepancy(List<Vector2> a_points, int a_width, int a_height)
        {
            const int BOXES_COUNT = 15;

            foreach (var p in a_points)
            {
                Debug.Assert(p.X >= 0);
                Debug.Assert(p.Y >= 0);
                Debug.Assert(p.X < a_width);
                Debug.Assert(p.Y < a_height);
            }

            double discrepancy = Double.MinValue;
            double area_field = a_width * a_height;

            for (double i = 1; i < BOXES_COUNT; i++)
            {
                double r = a_width * i / BOXES_COUNT;
                double t = a_height * i / BOXES_COUNT;

                double points_in_box = 0;
                foreach (var p in a_points)
                {
                    if (p.X >= r)
                        continue;
                    if (p.Y >= t)
                        continue;

                    points_in_box++;
                }

                double d = points_in_box / a_points.Count - (r * t) / area_field;

                if (d > discrepancy)
                    discrepancy = d;
            }

            return discrepancy;
        }
    }
}

